#!/usr/bin/env python3
# -*- mode: python -*-
# Copyright 2014-2016 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

"""Create example TLS certificates.

``region.crt``, ``cluster.crt``, and ``trust.crt`` will be created in
the current directory:

* ``region.crt`` is a PEM-encoded self-signed certificate and key.

* ``cluster.crt`` is a PEM-encoded certificate and key, signed by
  ``region.crt``.

* ``trust.crt`` is the PEM-encoded certificate *not key* for the region.

"""

from datetime import timedelta
from os import fchmod

from twisted.internet import ssl


def years_in_seconds(years):
    delta = timedelta(days=(years * 365))
    return int(delta.total_seconds())


# Create the region key and self-signed certificate.
region_key = ssl.KeyPair.generate(size=2048)
region_cert = region_key.selfSignedCert(
    serialNumber=1, CN="MAAS Region *TESTING*")


# Create a cluster key and a signing request.
cluster_key = ssl.KeyPair.generate(size=2048)
cluster_csr_data = cluster_key.certificateRequest(
    distinguishedName=ssl.DistinguishedName(CN="MAAS Cluster *TESTING*"))

# Sign the request with the *region* key.
cluster_cert_data = region_key.signCertificateRequest(
    issuerDistinguishedName=region_cert.getSubject(),
    requestData=cluster_csr_data, verifyDNCallback=(lambda dn: True),
    serialNumber=123, secondsToExpiry=years_in_seconds(5))

# Load the cluster certificate from the signed certificate.
cluster_cert = ssl.PrivateCertificate.load(
    data=cluster_cert_data, privateKey=cluster_key)


def write_certificate(cert, filename):
    assert isinstance(cert, ssl.Certificate)
    # Save the certificate.
    with open(filename, "wb") as fout:
        fchmod(fout.fileno(), 0o600)
        fout.write(ssl.Certificate.dumpPEM(cert))
    # Check that the certificate can be loaded back in.
    with open(filename, "rb") as fin:
        cert_in = ssl.Certificate.loadPEM(fin.read())
        assert cert_in == cert


def write_private_certificate(cert, filename):
    assert isinstance(cert, ssl.PrivateCertificate)
    # Save the certificate.
    with open(filename, "wb") as fout:
        fchmod(fout.fileno(), 0o600)
        fout.write(cert.dumpPEM())
    # Check that the certificate can be loaded back in.
    with open(filename, "rb") as fin:
        cert_in = ssl.PrivateCertificate.loadPEM(fin.read())
        assert cert_in == cert


# Save the region certificate with its key.
write_private_certificate(region_cert, "region.crt")

# Save the region certificate on its own.
write_certificate(ssl.Certificate(region_cert.original), "trust.crt")

# Save the cluster certificate with its key.
write_private_certificate(cluster_cert, "cluster.crt")
